/*
arp_rx_type
    0:request
    1:response
*/
module arp_rx #(
    parameter       SOURCE_IP       = {8'd192,8'd168,8'd7,8'd11}                                        
)(
    input                           i_clk                                   ,
    input                           i_rst                                   ,
    input   [31:0]                  i_set_source_ip                         ,
    input                           i_set_source_ip_valid                   ,
    output                          o_arp_rx_valid                          ,
    output  [31:0]                  o_arp_rx_ip                             ,
    output  [47:0]                  o_arp_rx_mac                            ,
    output  [15:0]                  o_arp_rx_type                           ,
    input                           s_axis_tvalid                           ,
    input   [7 : 0]                 s_axis_tdata                            ,
    input                           s_axis_tlast                            ,
    input   [32: 0]                 s_axis_tuser                            
);

    logic                           axis_rx_last                            ;
    logic   [31: 0]                 set_source_ip                           ;
    logic                           axi_rx_valid                            ;
    logic   [7 : 0]                 axis_rx_data                            ;
    logic   [15: 0]                 lsm_cnt                                 ;
    logic   [47: 0]                 rx_target_mac_addr                      ;
    logic   [31: 0]                 rx_target_ip_addr                       ;
    logic   [47: 0]                 rx_source_mac_addr                      ;
    logic   [31: 0]                 rx_source_ip_addr                       ;
    logic                           arp_rx_valid                            ;
    logic   [15: 0]                 arp_rx_type                             ;

    assign o_arp_rx_valid = arp_rx_valid;
    assign o_arp_rx_ip = rx_source_ip_addr;
    assign o_arp_rx_mac = rx_source_mac_addr;
    assign o_arp_rx_type = arp_rx_type;

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            set_source_ip <= SOURCE_IP;
        else if(i_set_source_ip_valid)
            set_source_ip <= i_set_source_ip;
        else 
            set_source_ip <= set_source_ip;
    end 



    //only recive arp package
    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            axi_rx_valid <= 0;
        else if(s_axis_tuser[31:16] == 16'h0806)
            axi_rx_valid <= s_axis_tvalid;
        else
            axi_rx_valid <= 0;
    end  

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            axis_rx_last <= 0;
        else 
            axis_rx_last <= s_axis_tlast;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            axis_rx_data <= 0;
        else
            axis_rx_data <= s_axis_tdata;
    end 
   
    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            lsm_cnt <= 0;
        else if(axi_rx_valid)
            lsm_cnt <= lsm_cnt + 1;
        else 
            lsm_cnt <= 0;
    end  

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            arp_rx_type <= 0;
        else if(lsm_cnt >= 6 && lsm_cnt <= 7)
            arp_rx_type <= {arp_rx_type[7:0], axis_rx_data};
        else 
            arp_rx_type <= arp_rx_type;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            rx_source_mac_addr <= 0;
        else if(lsm_cnt >= 8 && lsm_cnt <= 13)
            rx_source_mac_addr <= {rx_source_mac_addr[39:0], axis_rx_data};
        else 
            rx_source_mac_addr <= rx_source_mac_addr;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            rx_source_ip_addr <= 0;
        else if(lsm_cnt >= 14 && lsm_cnt <= 17)
            rx_source_ip_addr <= {rx_source_ip_addr[23:0], axis_rx_data};
        else 
            rx_source_ip_addr <= rx_source_ip_addr;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            rx_target_mac_addr <= 0;
        else if(lsm_cnt >= 18 && lsm_cnt <= 23)
            rx_target_mac_addr <= {rx_target_mac_addr[39:0], axis_rx_data};
        else 
            rx_target_mac_addr <= rx_target_mac_addr;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            rx_target_ip_addr <= 0;
        else if(lsm_cnt >= 24 && lsm_cnt <= 27)
            rx_target_ip_addr <= {rx_target_ip_addr[23:0], axis_rx_data};
        else 
            rx_target_ip_addr <= rx_target_ip_addr;
    end 


    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            arp_rx_valid <= 0;
        else if(axis_rx_last && axi_rx_valid && rx_target_ip_addr == set_source_ip)
            arp_rx_valid <= 1;
        else 
            arp_rx_valid <= 0;
    end 

   
   

endmodule
